package LimitedTimeGame.Day_0211;

/**
 * @author zxc
 * @date 2023/02/11 08:56
 **/

/**
 * 题目 ：装满杯子所需要的最短时长
 * 题目详述 ：
 * 现有一台饮水机，可以制备冷水、温水和热水。每秒钟，可以装满 2 杯 不同 类型的水或者 1 杯任意类型的水。
 * 给你一个下标从 0 开始、长度为 3 的整数数组 amount ，其中 amount[0]、amount[1] 和 amount[2] 分别表示需要装满冷水、温水和热水的杯子数量。
 * 返回装满所有杯子所需的 最少 秒数。
 *
 *提示：
 * amount.length == 3
 * 0 <= amount[i] <= 100
 *
 */
public class FillCups {
    public static void main(String[] args) {
        System.out.println(fillCups(new int[]{5 , 4 , 4}));
    }
    /**
     * 思路 ：
     * 假设f(i,j,k)为装满冷水i杯，温水j杯和热水k杯所需要的最少秒数;
     * ===>
     * 特殊情况 ：
     * （1）i == 0 && j == 0 && k == 0，即 f(0,0,0)最少秒数为0;
     * （2）（i == 0 && j == 0）||（i == 0 && k == 0）||（j == 0 && k == 0），
     *  ===> f(0,0,k) = k; f(0,j,0) = j;f(i,0,0) = i;
     * （3）i == 0 && j == 0 && k == 0，
     *  ===》 f(0,j,k) = max(j,k); f(i,0,k) = max(i,k); f(i,j,0) = max(i,j);
     *  一般情况 ：
     *  f(i,j,k) = min(f(i-1,j,k) , f(i,j-1,k) , f(i,j,k-1), f(i-1,j-1,k) , f(i-1,j,k-1) , f(i,j-1,k-1)) + 1;
     *
     * @param amount
     * @return
     */
    public static int fillCups(int[] amount) {
        int cold = amount[0];
        int warm = amount[1];
        int hot = amount[2];
        int[][][] dp = new int[cold + 1][warm + 1][hot + 1];
        dp[0][0][0] = 0;
        for(int i = 0; i <= cold ; i++){
            for(int j = 0 ; j <= warm ; j++){
                for(int k = 0 ; k <= hot ; k++){
//                    if(i == 0 && j > 0 && k> 0){
//                        dp[0][j % 2][k % 2] = Math.max(j , k);
//                    }
//                    if (i > 0 && j == 0 && k > 0){
//                        dp[i % 2][0][k % 2] = Math.max(i , k);
//                    }
//                    if(i > 0 && j > 0 && k == 0){
//                        dp[i % 2][j % 2][0] = Math.max(i , j);
//                    }
//                    if(i == 0 && j == 0 && k > 0){
//                        dp[0][0][k % 2] = k;
//                    }
//                    if(i > 0 && j == 0 && k == 0){
//                        dp[i % 2][0][0] = i;
//                    }
//                    if(i == 0 && j > 0 && k == 0){
//                        dp[0][j % 2][0] = j;
//                    }
//                    if(i > 0 && j > 0 && k > 0){
//                        int max1 = Math.min(Math.min(dp[(i - 1) % 2][j % 2][k % 2] , dp[i % 2][(j - 1) % 2][k % 2])
//                                , dp[i % 2][j % 2][(k - 1) % 2]);
//                        int max2 = Math.min(Math.min(dp[(i - 1) % 2][(j - 1) % 2][k % 2] , dp[i % 2][(j - 1) % 2][(k - 1) % 2])
//                                , dp[(i - 1) % 2][j % 2][(k - 1) % 2]);
//                        dp[i % 2][j % 2][k % 2] = Math.min(max1 , max2) + 1;
//                    }
                    if(i == 0 || j == 0 || k == 0){
                        if(i == 0 && j > 0 && k> 0){
                            dp[0][j][k] = Math.max(j , k);
                        }
                        if (i > 0 && j == 0 && k > 0){
                            dp[i][0][k] = Math.max(i , k);
                        }
                        if(i > 0 && j > 0 && k == 0){
                            dp[i][j][0] = Math.max(i , j);
                        }
                        if(i == 0 && j == 0 && k > 0){
                            dp[0][0][k] = k;
                        }
                        if(i > 0 && j == 0 && k == 0){
                            dp[i][0][0] = i;
                        }
                        if(i == 0 && j > 0 && k == 0){
                            dp[0][j][0] = j;
                        }
                    }
                    else {
                        int max1 = Math.min(Math.min(dp[i-1][j][k] , dp[i][j-1][k]), dp[i][j][k - 1]);
                        int max2 = Math.min(Math.min(dp[i-1][j-1][k] , dp[i][j-1][k-1]), dp[i-1][j][k-1]);
                        dp[i][j][k] = Math.min(max1 , max2) + 1;
                    }
                }
            }
        }
        return dp[cold][warm][hot];
    }
}
